#ifndef _MEM_FILE_H
#define _MEM_FILE_H
#include <assert.h>
#include <algorithm>
#include "common.h"
#include "logFile.h"

#define MEM_FILE memoryFile
#define MEM_FILE_STAT memoryFileStat
#define MEM_COLLECT memoryFileCollect
#define LIST_STR LIST<STRING>
#define PAIR std::pair
#define MEMORY_FILE_MAP MAP<int, memoryFile*>
#define MEMORY_COLLECT_MAP MAP<int, MEM_FILE_STAT*>
#define HEAD_STRUCT FileHeadStruct
#define APPEND_ITEM appendStruct
#define HEAD_LENGTH sizeof(HEAD_STRUCT)
#define TOP_POS 1
#define FILE_ALL_SIZE(size) size+HEAD_LENGTH
#define HEAD_POS(size) size-HEAD_LENGTH
#define MEM_FILE_ITEM memoryFileItem
#define CHAR_MEM memoryCharItem

typedef struct{
	FILE_RET_TYPE old_pos;
	FILE_RET_TYPE new_pos;
} appendStruct;

typedef struct{
	int num;
	FILE_LEN_TYPE size;
	FILE_LEN_TYPE position;
	FILE_LEN_TYPE shift;
	FILE_LEN_TYPE max;
	FILE_LEN_TYPE min;
}FileHeadStruct;

class memoryFile {
	public:
		LOCK lock;
		LOCK head_lock;
		FILE_LEN_TYPE position;
		LONG_INT fileSize;
		STRING fileName;
		int id;
		bool closed = true;
		FILE_LEN_TYPE max_value;
		FILE_LEN_TYPE min_value;

	private:
		FILE_STAT fileStat;
		char* mapped;

	public:
//		memoryFile();
		void load();
		void create(const char*, FILE_LEN_TYPE);
		LONG_INT loadMemory(const char *);
		char* createMemory(const char*, FILE_LEN_TYPE);
		void quit();
		void write(char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
		char* read(FILE_LEN_TYPE, FILE_LEN_TYPE);
		void flush();
		int readByte(FILE_LEN_TYPE);
		int find(char* , char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
		int compare(char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
		char* readMapper();
		HEAD_STRUCT* readHead();
		void writeHead(FILE_LEN_TYPE, FILE_LEN_TYPE, FILE_LEN_TYPE, FILE_LEN_TYPE);
		char* readHeadValue();
		void writeHead(void*);
		char* readPos(FILE_LEN_TYPE);
		void close_mem();
		FILE_LEN_TYPE tell();
		HEAD_STRUCT* seek(FILE_LEN_TYPE);
		HEAD_STRUCT* seek(FILE_LEN_TYPE, HEAD_STRUCT*);
		void setFileInfo(int, FILE_LEN_TYPE);
};


class memoryFileStat:public objectBase{
	private:
		int reference = 0;
		MEM_FILE* mem = new MEM_FILE();

	public:
		LOCK lock;
		bool destroy_stat = false;
		int run_stat_val = obj_stat::close_stat;
		void create();
		void destroy();
		bool alive();
		MEM_FILE* get_mem();
		void set_mem(MEM_FILE*);
};

class memoryCharItem:public VOBJECT<char, MEM_FILE_STAT>{
	public:
		memoryCharItem(char* val, MEM_FILE_STAT* mem_stat):VOBJECT<char, MEM_FILE_STAT>(val, mem_stat){};
		char* getChar();

};

class memoryFileItem:public OBJECT<MEM_FILE_STAT>{
//	private:
//		MEM_FILE* get();

	public:
		memoryFileItem(MEM_FILE_STAT* mem_stat):OBJECT<MEM_FILE_STAT>(mem_stat){};
		void create(const char*, FILE_LEN_TYPE);
		LONG_INT loadMemory(const char *);
		char* createMemory(const char*, FILE_LEN_TYPE);
		void quit();
		void write(char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
		char* read(FILE_LEN_TYPE, FILE_LEN_TYPE);
		void flush();
		int readByte(FILE_LEN_TYPE);
		int find(char* , char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
		int compare(char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
		CHAR_MEM readMapper();
		HEAD_STRUCT* readHead();
		void writeHead(FILE_LEN_TYPE, FILE_LEN_TYPE, FILE_LEN_TYPE, FILE_LEN_TYPE);
		char* readHeadValue();
		void writeHead(void*);
		char* readPos(FILE_LEN_TYPE);
		FILE_LEN_TYPE tell();
		HEAD_STRUCT* seek(FILE_LEN_TYPE);
		HEAD_STRUCT* seek(FILE_LEN_TYPE, HEAD_STRUCT*);
		MEM_FILE* get_mem();
		CHAR_MEM createChar(char*);
		FILE_LEN_TYPE get_max();
		FILE_LEN_TYPE get_min();
		void setFileInfo(int, FILE_LEN_TYPE);

};

class memoryFileCollect{
	private:
		MEMORY_COLLECT_MAP mem_map;
		int life = 10;
		LOCK lock;
		MEM_FILE_STAT* get(int);
		bool run_stat = true;
		int out_cout = 0;

	public:
		memoryFileCollect();
		MEM_FILE_STAT* get_stat(int);
		void push(int);
		void push(int, MEM_FILE_STAT*);
		MEM_FILE_ITEM readMemoryFile(int);
		void checkDestroy();
		bool exist(int);
		void erase(int);
		void close();
};

extern "C" int createMemory(const char*, FILE_LEN_TYPE);
extern "C" void closeMemory(int);
extern "C" void writeMemory(int, char*, FILE_LEN_TYPE, FILE_LEN_TYPE);
extern "C" char* readMemory(int, FILE_LEN_TYPE, FILE_LEN_TYPE);
extern "C" void flushMemory(int);
extern "C" int readByte(int, FILE_LEN_TYPE);
extern "C" FILE_LEN_TYPE tell(int);
extern "C" void seek(int, FILE_LEN_TYPE);
extern "C" int smallEndian();
extern "C" MEM_FILE_ITEM findMemoryFile(int);
extern "C" FILE_LEN_TYPE appendMemory(int, char*, FILE_LEN_TYPE);
void loadMemory(const char *, int&, int&);
void setFileInfo(int, int, FILE_LEN_TYPE);
FILE_LEN_TYPE appendMemory(int, char*, FILE_LEN_TYPE, FILE_RET_TYPE);
int getFileNum();
void writeHead(int, void*);


#endif
